package codename.carrot.bomberman.views.widgets;

//part of the view
import sheep.graphics.Image;
import sheep.math.BoundingBox;
import sheep.math.Vector2;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.MotionEvent;
import codename.carrot.bomberman.AppStorage;
import codename.carrot.bomberman.AppStorage.Direction;

/**
 * Draws the joystick and reacts to touch gestures on it. 
 * @author Group A4
 */
public class JoystickWidget extends BombermanWidget {
	
	private static final boolean SET_TOUCH_BOUNDS = true, SET_PAD_BOUNDS = false;
	private Vector2 joystickPos, controllPadPos, controllPadCenter;
	private Image controllPad;
	/**
	 * Image used to show the joystick in the GUI.
	 */
	private Image joystick;
	/**
	 * Default direction of the widget's direction pointer set to right. 
	 */
	private Direction direction = Direction.RIGHT;
	/**
	 * The widget performs actions only when it's listening (when isListening is set to true)
	 */
	private boolean isListening = false;
	/**
	 * The widget's bounding box, that defines it's touch response area in the GUI. 
	 */
	private BoundingBox touchBounds, controlPadBounds;
	
	/**
	 * Enum used to start and stop movement of the widget's direction pointer. 
	 * @author Group A4
	 */
	public enum MoveState {
		START, STOP
	};

	/**
	 * Class constructor. Sets position and bounds for the widget. 
	 * @param pad - the controller pad area
	 * @param stick - the joystick
	 */
	public JoystickWidget(Image pad, Image stick) {
		this.controllPad = pad;
		this.joystick = stick;
		this.controllPadPos = new Vector2(controllPad.getWidth()/3, (float)(AppStorage.SCREEN_HEIGHT_GAME-controllPad.getHeight()*1.25));
		this.controllPadCenter = new Vector2(controllPadPos.getX()+controllPad.getWidth()/2, controllPadPos.getY()+controllPad.getWidth()/2);
		this.joystickPos = new Vector2(controllPadCenter.getX()-joystick.getHeight()/2, controllPadCenter.getY()-joystick.getHeight()/2);
		this.touchBounds = setBoundingBox(JoystickWidget.SET_TOUCH_BOUNDS);
		this.controlPadBounds = setBoundingBox(JoystickWidget.SET_PAD_BOUNDS);
	}
	/**
	 * Sets the bounding box of the joystick widget. When a user clicks within the control-pad
	 * the bounding box covers half of the screen. If interacting with the joystick from outside
	 * the control-pad, the bounding area is limited to the control-pad's area. 
	 * @param touch
	 * @return The bounding box.
	 */
	private BoundingBox setBoundingBox(boolean touch) {
		Rect bounds = new Rect();
		/**
		 * If interacting within the control-pad
		 */
		if(touch){
			bounds.left = 0;
			bounds.right = AppStorage.SCREEN_WIDTH_GAME / 2;
			bounds.top = 0;
			bounds.bottom = AppStorage.SCREEN_HEIGHT_GAME;
		/**
		 * If interacting from outside the control-pad
		 */
		} else {
			bounds.left = (int)controllPadPos.getX();
			bounds.right = (int)(controllPadPos.getX()+controllPad.getWidth());
			bounds.top = (int)controllPadPos.getY();
			bounds.bottom = (int)(controllPadPos.getY()+controllPad.getHeight());
		}
		return new BoundingBox(bounds);
	}

	@Override
	public void draw(Canvas canvas) {
		controllPad.draw(canvas, controllPadPos.getX(), controllPadPos.getY());
		joystick.draw(canvas, joystickPos.getX(), joystickPos.getY());
	}

	@Override
	public boolean onTouchDown(MotionEvent event) {
		super.onTouchDown(event);
		/**
		 * The widget listens on movement when interacting within the bounding box. 
		 */
		if(controlPadBounds.contains(event.getX(), event.getY()))
				isListening = true;
		if (touchBounds.contains(event.getX(), event.getY())){
			float dx = (event.getX()-controllPadCenter.getX()), dy = (event.getY()-controllPadCenter.getY());
			double distanceFromCenter = Math.sqrt(dx*dx + dy*dy);
			double angle = Math.atan2(dy, dx);
			
			/**
			 * If the widget listens, move the joystick. 
			 */
			if(isListening){
				if(distanceFromCenter > controllPad.getWidth()/2){
					this.joystickPos = new Vector2((float)((controllPad.getWidth()/2 * Math.cos(angle))+controllPadCenter.getX()),(float)((controllPad.getWidth()/2 * Math.sin(angle))+controllPadCenter.getY()));
				} else {
					this.joystickPos = new Vector2(event.getX(), event.getY());
				}
				
				this.joystickPos.subtract(new Vector2(joystick.getHeight()/2, joystick.getWidth()/2));
				this.direction = AppStorage.getDirection((float)angle);
				
				alertListeners(new JoysticWidgetAction(this,MoveState.START, direction));
			}
			return true;
		}
		return false;
	}

	@Override
	public boolean onTouchUp(MotionEvent event) {
		super.onTouchUp(event);
		isListening = false;
		alertListeners(new JoysticWidgetAction(this,MoveState.STOP, null));
		this.joystickPos = new Vector2(controllPadCenter.getX()-joystick.getHeight()/2, controllPadCenter.getY()-joystick.getHeight()/2);
		return false;
	}
}
